import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:p_location/common/res/common_res.dart';
import 'package:p_location/common/widget/loading_dialog.dart';
import 'package:p_location/net/http_method.dart';
import 'package:p_location/user/ui/login_page.dart';
import 'package:p_location/utils/net_utils.dart';
import 'package:p_location/utils/string_util.dart';
import 'package:p_location/utils/toast_util.dart';
import 'package:connectivity/connectivity.dart';

import 'http_option.dart';
import 'net_constants.dart';
import 'net_listener.dart';

class DioHttpClient {
  static bool isProxyChecked = false;

//  static String proxy = '';

  static String proxy = "";

//  static String proxy = "172.16.10.241:8888";

  static String baseUrl = "https://c4.joysuch.com/";

  static String pdfUrl = 'http://10.8.1.86:9091/';

  //fir 更新的地址
  static const String UPDATE_URL = "http://api.bq04.com";

  //qa
  static String qaBaseUrl = "http://10.8.1.89:9999/";
  static String qaPdfUrl = 'http://10.8.1.80:9091/';
  static const int CONNECTION_TIME_OUT = 60000;
  static const int RECEIVE_TIME_OUT = 60000;

  static String fileUrl = '$baseUrl/image/view?id=';

  static final Map<String, String> headers = Map();

  static const cookieInfo = "7ee93076-2afe-4273-90b9-97e89d72c853";

  static void setHeaders(String token) {
//    headers['Content-Type'] = 'application/json;charset=UTF-8';
//    headers['Authorization'] = token;
//    headers['Connection'] = 'keep-alive';

    String zzz =
        'Qs_lvt_337467=1620617771,1623304582; Hm_lvt_ea07555597c557a7ec31c21bc463bbc2=1623304582; Hm_lvt_a6258bd94f0c50b2af22da498500079b=1623304582; Qs_pv_337467=4455367511928911400,3358380573814507000,2811147531629205500,3008426404623669000,933277069928344300; sidebarStatus=0; loginCookie=$cookieInfo; joysuch-Token=login';
    headers['cookie'] = zzz;
    print("cookie" + token);
  }

  static void addHeader(String key, String value) {
    if (StringUtil.isNotEmpty(key) && StringUtil.isNotEmpty(value)) {
      headers[key] = value;
    }
  }

  static bool isEmptyToken() {
    String token = headers['Authorization'];
    return StringUtil.isEmpty(token);
  }

  static Future<Response> fetchPut(List params, String url) async {
    checkNetWorkAvailable(null);
    Dio dio = Dio(BaseOptions(
        baseUrl: baseUrl,
        headers: headers,
        contentType: 'application/x-www-form-urlencoded'));
    proxyHandler(dio);
    Map<String, dynamic> paramMap = {};
    params.sort();
    params.forEach((listItem) {
      List temp = listItem.toString().split('=');
      paramMap[temp[0]] = temp[1];
    });
    Response response = await dio.put(url,
        data: paramMap,
        options: Options(contentType: 'application/x-www-form-urlencoded'));
//    print(response.data);
    if (response.statusCode == HttpStatus.ok) {
      return response;
    }
    return null;
  }

  /*
   * 上传文件
   */
  static Future<Response> uploadFile(BuildContext context, String bucketType,
      String urlPath, File image) async {
    checkNetWorkAvailable(null);
    Response response;
    Dio dio = Dio(BaseOptions(
        baseUrl: baseUrl,
        headers: headers,
        contentType: 'application/x-www-form-urlencoded'));
    proxyHandler(dio);
    try {
//      String path = image.path;
//      var name = path.substring(path.lastIndexOf("/") + 1, path.length);
//      var suffix = name.substring(name.lastIndexOf(".") + 1, name.length);
//      FormData formData = new FormData.from({
//        'bucketType': bucketType,
//        "file": new UploadFileInfo(new File(path), name,
//            contentType: ContentType.parse("image/$suffix"))
//      });
//      showDialog<Null>(
//          context: context, //BuildContext对象
//          barrierDismissible: true,
//          builder: (BuildContext context) {
//            return new LoadingDialog(text: '上传中,请稍后...');
//          });
//      response = await dio.post(urlPath, data: formData);
//      if (response.statusCode == 200) {
//        Navigator.pop(context);
//        print('uploadFile success---------${response.data}');
//      }
    } on DioError catch (e) {
      Navigator.pop(context);
      print('uploadFile error---------$e');
//      formatError(e);
    }
    return response;
  }

  static void proxyHandler(Dio dio) {
    if (dio == null) {
      return;
    }
    if (isProxyChecked) {
      (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
          (client) {
        client.badCertificateCallback =
            (X509Certificate cert, String host, int port) {
          return isProxyChecked && Platform.isAndroid;
        };
        client.findProxy = (url) {
          return 'PROXY $proxy';
        };
      };
    }
  }

  static Future<bool> checkNetWorkAvailable(NetListener callback) async {
    bool isNetWorkAvailable = false;
    var connectivityResult = await (Connectivity().checkConnectivity());
//    print(connectivityResult);
    if (connectivityResult == ConnectivityResult.none) {
      if (callback != null) {
        CommonRes res = CommonRes(code: -1, msg: '暂无网络', data: null);
//        print(res.toString());
        callback?.onRequestError(res);
      }
      isNetWorkAvailable = false;
    } else {
      isNetWorkAvailable = true;
    }
    return isNetWorkAvailable;
  }

  static CommonRes getErrorMsg(int code) {
    CommonRes errorRes =
        CommonRes(code: code, msg: NetConstants.ERROR_DEFAULT_STRING);
    if (StringUtil.isNotEmpty(NetConstants.ERROR_MAP[code])) {
      errorRes.msg = NetConstants.ERROR_MAP[code];
    }
    return errorRes;
  }

  static requestGet(BuildContext context, String url,
      Map<String, dynamic> params, NetListener callback,
      {CancelToken cancelToken, bool isUpdate = false}) {
    HttpOption httpOption = HttpOption(
        contentType: 'application/x-www-form-urlencoded',
        callback: callback,
        cancelToken: cancelToken);
    sendRequest(context, isUpdate ? HttpMethod.UPDATE : HttpMethod.GET, url,
        params, httpOption);
  }

  static requestPost(BuildContext context, String url,
      Map<String, dynamic> params, NetListener callback,
      {String contentType,
      CancelToken cancelToken,
      String loadingTip,
      dynamic data}) {
    HttpOption httpOption = HttpOption(
        contentType: contentType ?? NetConstants.POST_TYPE_JSON,
        callback: callback,
        cancelToken: cancelToken,
        loadingTip: loadingTip,
        data: data);
    sendRequest(context, HttpMethod.POST, url, params, httpOption);
  }

  static requestPut(BuildContext context, String url,
      Map<String, dynamic> params, NetListener callback,
      {String contentType, CancelToken cancelToken}) {
    HttpOption httpOption = HttpOption(
        contentType: contentType ?? NetConstants.POST_TYPE_FORM,
        callback: callback,
        cancelToken: cancelToken);
    sendRequest(context, HttpMethod.POST, url, params, httpOption);
  }

  static requestDelete(BuildContext context, String url,
      Map<String, dynamic> params, NetListener callback,
      {CancelToken cancelToken}) {
    HttpOption httpOption = HttpOption(
        contentType: NetConstants.POST_TYPE_JSON,
        callback: callback,
        cancelToken: cancelToken);
    sendRequest(context, HttpMethod.DELETE, url, params, httpOption);
  }

  static requestDownload(BuildContext context, String urlPath, String savePath,
      NetListener callback,
      {CancelToken cancelToken}) {
    if (StringUtil.isEmpty(urlPath)) {
      print('$urlPath不能为空!');
      return null;
    }
    if (StringUtil.isEmpty(savePath)) {
      print('$savePath不能为空!');
      return null;
    }
    HttpOption httpOption = HttpOption(
        contentType: NetConstants.POST_TYPE_FORM,
        callback: callback,
        savePathForDownload: savePath,
        cancelToken: cancelToken);
    sendRequest(context, HttpMethod.DOWNLOAD, urlPath, {}, httpOption);
  }

  static sendRequest(BuildContext context, HttpMethod httpMethod, String url,
      Map<String, dynamic> params, HttpOption httpOption) async {
    if (!httpOption.isValid()) {
      return;
    }
    checkNetWorkAvailable(httpOption.callback).then((flag) {
      if (flag) {
        realRequest(context, httpMethod, url, params, httpOption);
      }
    });
  }

  static realRequest(BuildContext context, HttpMethod httpMethod, String url,
      Map<String, dynamic> params, HttpOption httpOption) async {
    try {
      Dio dio = Dio(BaseOptions(
          baseUrl: httpMethod == HttpMethod.DOWNLOAD
              ? fileUrl
              : (httpMethod == HttpMethod.UPDATE ? UPDATE_URL : baseUrl),
          headers: headers,
          connectTimeout: CONNECTION_TIME_OUT,
          contentType: httpOption.contentType));
//      print('dio---' + (httpMethod == HttpMethod.DOWNLOAD ? fileUrl : baseUrl));
      proxyHandler(dio);
      Response response;
      if (httpMethod == HttpMethod.GET || httpMethod == HttpMethod.UPDATE) {
        response = await dio.get(url,
            queryParameters: params,
            cancelToken: httpOption.cancelToken,
            options: Options(
              sendTimeout: CONNECTION_TIME_OUT,
              receiveTimeout: RECEIVE_TIME_OUT,
            ));
      } else if (httpMethod == HttpMethod.POST) {
        if (!StringUtil.isEmpty(httpOption.loadingTip)) {
          showDialog<Null>(
              context: context, //BuildContext对象
              barrierDismissible: false,
              builder: (BuildContext context) {
                return WillPopScope(
                  child: new LoadingDialog(text: httpOption.loadingTip),
                  onWillPop: () async {
                    return Future.value(false);
                  },
                );
              });
        }
        response = await dio.post(url,
            data: httpOption.data != null ? httpOption.data : params,
            options: Options(
                sendTimeout: CONNECTION_TIME_OUT,
                receiveTimeout: RECEIVE_TIME_OUT,
                contentType: httpOption.contentType));
      } else if (httpMethod == HttpMethod.PUT) {
        response = await dio.put(url,
            data: params,
            options: Options(
                sendTimeout: CONNECTION_TIME_OUT,
                contentType: httpOption.contentType));
      } else if (httpMethod == HttpMethod.DELETE) {
        response = await dio.delete(url,
            data: params,
            options: Options(contentType: httpOption.contentType));
      } else if (httpMethod == HttpMethod.DOWNLOAD) {
        response = await dio.download(url, httpOption.savePathForDownload,
            onReceiveProgress: (int count, int total) {
          print("count:$count total:$total");
        });
      }
//      print(response.data);
      if (!StringUtil.isEmpty(httpOption.loadingTip)) {
        Navigator.of(context).pop();
      }
      if (response.statusCode == HttpStatus.ok) {
        if (response != null && response.data != null) {
          if (response.data["code"] == 0) {
            httpOption.callback?.onRequestSuccess(response);
          } else {
            if (response.data["code"] == -2) {
//              ToastUtil.showToast(NetConstants.ERROR_MAP[401]);
              Navigator.pushAndRemoveUntil(
                context,
                new MaterialPageRoute(builder: (context) => LoginPage()),
                (route) => route == null,
              );
            } else {
              httpOption.callback?.onRequestError(CommonRes(
                  code: response.data["code"], msg: response.data["msg"]));
            }
          }
        } else {
          httpOption.callback?.onRequestError(getErrorMsg(-1));
        }
      }
    } on DioError catch (e) {
      if (!StringUtil.isEmpty(httpOption.loadingTip)) {
        Navigator.of(context).pop();
      }
      print("请求异常:" + e.toString());
//      print("异常信息:" + e.error);
      if (e.type == DioErrorType.receiveTimeout) {
//        ToastUtil.showToast(NetConstants.ERROR_MAP[801]);
        httpOption.callback?.onRequestError(getErrorMsg(801));
      } else if (NetUtils.check(e.message)) {
//        ToastUtil.showToast(NetConstants.ERROR_MAP[802]);
        httpOption.callback?.onRequestError(getErrorMsg(802));
      } else if (e.response?.statusCode == 401) {
        ToastUtil.showToast(NetConstants.ERROR_MAP[401]);
        Navigator.pushAndRemoveUntil(
          context,
          new MaterialPageRoute(builder: (context) => LoginPage()),
          (route) => route == null,
        );
      } else {
        httpOption.callback
            ?.onRequestError(getErrorMsg(e.response?.statusCode ?? -1));
      }
    }
  }
}
